Skip to content

refactor(api): serve remaining services via axum (rm tide 2/5) - #4704

Draft
sveitser wants to merge 26 commits into
mainfrom
ma/axum-services
Draft

refactor(api): serve remaining services via axum (rm tide 2/5)#4704
sveitser wants to merge 26 commits into
mainfrom
ma/axum-services

Conversation

@sveitser

Copy link
Copy Markdown
Collaborator
  • ports relay server, dev-node, prover, node bins, orchestrator,
    node-metrics, lcqs, standalone builder to axum
  • clients stay on surf-disco
  • orchestrator decodes surf-disco's double-vbs-wrapped bodies
  • builder /healthcheck stays decodable by hotshot task-impls
  • node-metrics scrapes identity from /v1/status/metrics

Review focus: orchestrator body decoding (12-byte envelope strip);
per-service healthcheck bodies.

@gemini-code-assist

Copy link
Copy Markdown
Contributor
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Switch espresso-node's serve modes (full, fs, status-only, bare) to the
in-repo axum server. The tide-disco App is still constructed so the
module definitions keep compiling; it no longer binds the API port.

Restores tide-disco wire parity on the axum server: tide-compatible
paths and /v0 URI rewrites (without the unconsumed v0 legacy
availability formats), reward-state and namespace proof endpoints,
tide 404/400 statuses on reward endpoints, accept-negotiated JSON/vbs
healthcheck bodies (AppHealth shape at top level, bare HealthStatus
per module), and ws Close frames on stream completion.
@sveitser
sveitser force-pushed the ma/axum-server-core branch from 41fb01c to 041b34a Compare July 17, 2026 00:21
sveitser added 3 commits July 17, 2026 08:46
The separate axum_port option was removed when axum took over the main
ESPRESSO_NODE_API_PORT; these .env entries have no consumer.
…a axum

State-signature relay server, espresso-dev-node, hotshot-state-prover,
submit-transactions, and nasty-client bind axum servers with
tide-disco-compatible routes, bodies, and healthchecks (bare
HealthStatus, accept-negotiated JSON or vbs). Clients stay on
surf-disco.
Ports the remaining tide-disco servers. The orchestrator decodes
surf-disco's double-vbs-wrapped request bodies; node-metrics scrapes
node identity from /v1/status/metrics; the standalone builder's
/healthcheck stays decodable as HealthStatus by hotshot task-impls.
Clients stay on surf-disco.
sveitser added 21 commits July 17, 2026 14:53
Convert the 15 v1 module routers to aide's ApiRouter and annotate all
171 routes with summaries and descriptions lifted from the legacy
tide-disco toml specs, restoring the docs that died with the tide App.
Serve the spec at /v1/docs/openapi.json with Swagger UI at /v1 and
Scalar at /v1/scalar. Point / at /v1 (temporary redirect) while the
v2 API is a work in progress.

Wire-neutral: ApiJson delegates to axum::Json, so response bytes,
statuses, and headers are unchanged; the OpenAPI spec reports untyped
200 responses instead of adding JsonSchema derives to domain types.
The docs routes and OpenAPI finish lived only in create_router_v1,
which no serve mode calls: the serve modes compose module routers
directly, so the running node 404'd on /v1 while the unit tests
passed. Extract finish_v1_docs() and route all four serve modes
(full, fs, status, bare) through it; the generated spec now reflects
exactly the modules each mode mounts. Regression test assembles the
router the way serve_axum_status does, wrapped in the production
top-level-routes and legacy-URI-rewrite layers.
aide only derives path parameters from named-struct Path<T>
extractors; the v1 handlers all use primitives and tuples, so every
operation showed zero parameters and Swagger's try-it-out could not
fill the URL templates. Declare a required string parameter for every
{name} template segment after finish_api (string because primitive
extractors carry no type metadata; handlers parse).

Also: Swagger UI opens operations with try-it-out enabled; the
test_api example moves to port 5001 (macOS AirPlay holds 5000) and
its startup log lists the v1 doc URLs.
Numeric template segments (height, from/until, epoch, view, index,
limit, offset, namespace, finalized, ...) are declared as unsigned
integers, matching each handler's Path<T> extractor; hash, key, and
address segments stay strings. Unknown future names default to string.
Documentation-only: handlers parse the raw segment regardless.
The first path segment after /v1/ becomes the operation's OpenAPI tag,
so Swagger renders one collapsible section per module (availability,
status, catchup, ...), sorted.
Palette from the staking UI: cream background, coffee headings,
cookie-brown GET and orange POST accents; topbar hidden.
Review feedback: 44 in-function use statements move to the file
header; long v0_3/v0_4 turbofish paths shortened via imports; the
shared last_merklized_state_height comment now names all state
modules.
Review feedback: the macro now stringifies the parameter ident instead
of taking a redundant string. Also fixes namespace_proof_by_payload_hash,
whose "payload-hash" literal never matched the {payload_hash}
placeholder, leaving it unsubstituted in built paths.
Review findings. tower's concurrency permit is released at the 101
upgrade, so websockets escaped ESPRESSO_NODE_API_MAX_CONNECTIONS
entirely; a shared semaphore now gives plain requests a slot while in
flight and streaming sockets one for their lifetime, with a real-TCP
regression test.

The API port also binds before router composition: OpenAPI generation
takes ~0.5s in debug builds, and clients connecting during it now
queue in the accept backlog instead of being refused. This is what
broke the test-postgres shards: first-request test helpers panic on a
refused connection.
drive_ws_stream only noticed a dead client on the next send, so a
socket whose stream was quiet held its max_connections slot and its
stream task forever; reconnect churn exhausted the demo's budget of 25
and every plain request got 429, killing the native-demo e2e tests
(claim-rewards-loop exits on non-404 and tears the demo down). Poll
the client side with select so disconnects release the slot and end
the task immediately. Regression test now uses a never-yielding
stream.
The demo's nasty-client holds up to 100 open streams per resource type
by design, against a request budget of 25; counting sockets for their
lifetime starved every plain request on node-1 with 429 and killed the
native-demo e2e tests. max_connections goes back to bounding in-flight
requests only (as in every green run); a socket's slot is released at
the 101 upgrade. Stream tasks still end promptly on client disconnect,
which was the actual leak.
Base automatically changed from ma/axum-server-core to main July 24, 2026 07:27
Conflicts came from #4703 landing on main as a squash, so main already
carries most of this branch's node-API work.

- api.rs: keep this branch's removal of the legacy v0 namespace-proof
  test alongside main's new check_light_client_proofs/stake_table helpers
- api/state.rs: keep main's lc_leaf_proof_chain_limit helper
- process-compose.yaml: drop QUERY_SERVICE_URI/NODE_VALIDATOR_URI, whose
  only consumer (the docker block-explorer process) main removed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants